package com.yugao.fintech.antelope.pay.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yugao.fintech.antelope.base.exception.enums.GlobalErrorEnum;
import com.yugao.fintech.antelope.pay.common.assembly.MchPayPassageAssembly;
import com.yugao.fintech.antelope.pay.common.constants.Cs;
import com.yugao.fintech.antelope.pay.common.manager.MchAppManager;
import com.yugao.fintech.antelope.pay.common.manager.PayInterfaceConfigManager;
import com.yugao.fintech.antelope.pay.common.manager.PayMqSender;
import com.yugao.fintech.antelope.pay.common.manager.PayWayManager;
import com.yugao.fintech.antelope.pay.common.mapper.MchPayPassageMapper;
import com.yugao.fintech.antelope.pay.common.model.mq.ResetIsvMchAppInfoConfigMQ;
import com.yugao.fintech.antelope.pay.common.service.MchPayPassageService;
import com.yugao.fintech.antelope.pay.common.service.PayInterfaceDefineService;
import com.yugao.fintech.antelope.pay.model.rqrs.MchPayPassageConfigQL;
import com.yugao.fintech.antelope.pay.model.rqrs.MchPayPassageRQ;
import com.yugao.fintech.antelope.pay.model.rqrs.MchPayPassageRS;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service
public class MchPayPassageServiceImpl extends ServiceImpl<MchPayPassageMapper, MchPayPassage>
        implements MchPayPassageService {
    @Autowired
    private PayWayManager payWayManager;
    @Autowired
    private PayInterfaceConfigManager payInterfaceConfigManager;
    @Autowired
    private MchPayPassageAssembly mchPayPassageAssembly;
    @Autowired
    private MchAppManager mchAppManager;
    @Autowired
    private PayInterfaceDefineService payInterfaceDefineService;
    @Autowired
    private PayMqSender payMqSender;

    @Override
    public List<MchPayPassageRS> listPayPassage(@Validated MchPayPassageConfigQL query) {
        List<MchPayPassageRS> resp = new ArrayList<>();
        LambdaQueryWrapper<PayInterfaceConfig> lqw = PayInterfaceConfig.lqw()
                .eq(PayInterfaceConfig::getInfoId, query.getAppId())
                .eq(StringUtils.isNotEmpty(query.getIfCode()), PayInterfaceConfig::getIfCode, query.getIfCode());
        List<PayInterfaceConfig> payIfConfigList = payInterfaceConfigManager.list(lqw);
        payIfConfigList.forEach(payIfConfig -> {
            PayInterfaceDefine define = payInterfaceDefineService.getByIfCode(payIfConfig.getIfCode());
            // 支付方式集合
            LambdaQueryWrapper<PayWay> wrapper = PayWay.lqw()
                    .in(Objects.nonNull(define.getWayCodes()), PayWay::getWayCode, define.getWayCodes())
                    .eq(StringUtils.isNotEmpty(query.getWayCode()), PayWay::getWayCode, query.getWayCode())
                    .like(StringUtils.isNotEmpty(query.getWayName()), PayWay::getWayName, query.getWayName());
            List<PayWay> payWayList = payWayManager.list(wrapper);

            if (!CollectionUtils.isEmpty(payWayList)) {
                // 支付方式代码集合
                List<String> wayCodeList = payWayList.stream().map(PayWay::getWayCode).collect(Collectors.toList());

                MchApp mchApp = mchAppManager.getById(query.getAppId());
                if (Objects.isNull(mchApp)) {
                    throw new BizException(GlobalErrorEnum.OPERATION_FAIL_SELETE);
                }
                // 商户支付通道集合
                Map<String, MchPayPassage> mchPayPassageMap = this.list(MchPayPassage.lqw()
                                .select(MchPayPassage::getWayCode, MchPayPassage::getStatus, MchPayPassage::getId)
                                .eq(MchPayPassage::getAppId, query.getAppId())
                                .eq(MchPayPassage::getMchNo, mchApp.getMchNo())
                                .in(MchPayPassage::getWayCode, wayCodeList))
                        .stream()
                        .collect(Collectors.toMap(MchPayPassage::getWayCode, Function.identity()));

                for (PayWay payWay : payWayList) {
                    MchPayPassageRS.MchPayPassageRSBuilder builder = MchPayPassageRS.builder()
                            .appId(query.getAppId()).ifCode(define.getIfCode())
                            .status(Cs.NO).wayCode(payWay.getWayCode()).wayName(payWay.getWayName());
                    // 某种支付方式多个通道的情况下，只要有一个通道状态为开启，则该支付方式对应为开启状态
                    MchPayPassage dbRecord = mchPayPassageMap.get(payWay.getWayCode());
                    if (Objects.nonNull(dbRecord)) {
                        if (Cs.YES.equals(dbRecord.getStatus())) {
                            builder.status(Cs.YES);
                        }
                        builder.id(dbRecord.getId());
                    }
                    resp.add(builder.build());
                }

            }
        });

        return resp.stream()
                .filter(e -> StringUtils.isEmpty(query.getStatus()) || e.getStatus().equals(query.getStatus()))
                .collect(Collectors.toList());
    }

    @Override
    public MchPayPassageRS getPayPassage(Long payPassageId) {
        if (Objects.isNull(payPassageId)) {
            return null;
        }
        return mchPayPassageAssembly.toMchPayPassageResp(this.getById(payPassageId));
    }

    @Override
    public void saveOrUpdatePayPassage(MchPayPassageRQ req) {
        MchApp mchApp = mchAppManager.getById(req.getAppId());
        if (Objects.isNull(mchApp)) {
            throw new BizException(GlobalErrorEnum.OPERATION_FAIL_SELETE);
        }
        String mchNo = mchApp.getMchNo();
        MchPayPassage mchPayPassage = mchPayPassageAssembly.toMchPayPassage(req);
        mchPayPassage.setMchNo(mchNo);
        if (mchPayPassage.getRate() != null) {
            mchPayPassage.setRate(mchPayPassage.getRate().divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP));
        } else {
            mchPayPassage.setRate(BigDecimal.ZERO);
        }
        this.saveOrUpdate(mchPayPassage);

        // 推送修改消息
        ResetIsvMchAppInfoConfigMQ mq = ResetIsvMchAppInfoConfigMQ
                .build(ResetIsvMchAppInfoConfigMQ.RESET_TYPE_MCH_APP, null, mchApp.getMchNo(), mchApp.getId());
        payMqSender.send(mq);
    }

    @Override
    public MchPayPassage getMchPayPassage(String mchNo, String appId, String wayCode) {
        LambdaQueryWrapper<MchPayPassage> lqw = MchPayPassage.lqw()
                .eq(MchPayPassage::getMchNo, mchNo).eq(MchPayPassage::getAppId, appId)
                .eq(MchPayPassage::getWayCode, wayCode);
        return this.getOne(lqw);
    }
}
